home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / recent2 / qamitrack1.80.lha / QAmiTrack / source / TrackRexx.c < prev    next >
C/C++ Source or Header  |  1997-04-06  |  16KB  |  871 lines

  1. /*
  2.  * Source generated with ARexxBox 1.12 (May 18 1993)
  3.  * which is Copyright (c) 1992,1993 Michael Balzer
  4.  */
  5.  
  6. #include <exec/types.h>
  7. #include <exec/memory.h>
  8. #include <dos/dos.h>
  9. #include <rexx/storage.h>
  10. #include <rexx/rxslib.h>
  11.  
  12. #ifdef __GNUC__
  13. /* GCC needs all struct defs */
  14. #include <dos/exall.h>
  15. #include <graphics/graphint.h>
  16. #include <intuition/classes.h>
  17. #include <devices/keymap.h>
  18. #include <exec/semaphores.h>
  19. #endif
  20.  
  21. #include <clib/alib_protos.h>
  22. #include <clib/exec_protos.h>
  23. #include <clib/dos_protos.h>
  24. #include <clib/rexxsyslib_protos.h>
  25.  
  26. #ifndef __NO_PRAGMAS
  27.  
  28. #ifdef AZTEC_C
  29. #include <pragmas/exec_lib.h>
  30. #include <pragmas/dos_lib.h>
  31. #include <pragmas/rexxsyslib_lib.h>
  32. #endif
  33.  
  34. #ifdef LATTICE
  35. #include <pragmas/exec_pragmas.h>
  36. #include <pragmas/dos_pragmas.h>
  37. #include <pragmas/rexxsyslib_pragmas.h>
  38. #endif
  39.  
  40. #endif /* __NO_PRAGMAS */
  41.  
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <ctype.h>
  46.  
  47. #ifdef LATTICE
  48. #undef toupper
  49. #define inline __inline
  50. #endif
  51.  
  52. #ifdef __GNUC__
  53. #undef toupper
  54. static inline char toupper( char c )
  55. {
  56.     return( islower(c) ? c - 'a' + 'A' : c );
  57. }
  58. #endif
  59.  
  60. #ifdef AZTEC_C
  61. #define inline
  62. #endif
  63.  
  64. #include <dos/rdargs.h>
  65.  
  66. #include "TrackRexx.h"
  67.  
  68. struct rxs_stemnode
  69. {
  70.     struct rxs_stemnode *succ;
  71.     char *name;
  72.     char *value;
  73. };
  74.  
  75.  
  76. extern struct ExecBase *SysBase;
  77. extern struct DosLibrary *DOSBase;
  78. extern struct RxsLib *RexxSysBase;
  79.  
  80. void (*ARexxResultHook)( struct RexxHost *, struct RexxMsg * ) = NULL;
  81.  
  82.  
  83.  
  84. void ReplyRexxCommand(
  85.     struct RexxMsg    *rexxmessage,
  86.     long            primary,
  87.     long            secondary,
  88.     char            *result )
  89. {
  90.     if( rexxmessage->rm_Action & RXFF_RESULT )
  91.     {
  92.         if( primary == 0 )
  93.         {
  94.             secondary = result
  95.                 ? (long) CreateArgstring( result, strlen(result) )
  96.                 : (long) NULL;
  97.         }
  98.         else
  99.         {
  100.             char buf[16];
  101.             
  102.             if( primary > 0 )
  103.             {
  104.                 sprintf( buf, "%ld", secondary );
  105.                 result = buf;
  106.             }
  107.             else
  108.             {
  109.                 primary = -primary;
  110.                 result = (char *) secondary;
  111.             }
  112.             
  113.             SetRexxVar( (struct Message *) rexxmessage,
  114.                 "RC2", result, strlen(result) );
  115.             
  116.             secondary = 0;
  117.         }
  118.     }
  119.     else if( primary < 0 )
  120.         primary = -primary;
  121.     
  122.     rexxmessage->rm_Result1 = primary;
  123.     rexxmessage->rm_Result2 = secondary;
  124.     ReplyMsg( (struct Message *) rexxmessage );
  125. }
  126.  
  127.  
  128. void FreeRexxCommand( struct RexxMsg *rexxmessage )
  129. {
  130.     if( !rexxmessage->rm_Result1 && rexxmessage->rm_Result2 )
  131.         DeleteArgstring( (char *) rexxmessage->rm_Result2 );
  132.  
  133.     if( rexxmessage->rm_Stdin &&
  134.         rexxmessage->rm_Stdin != Input() )
  135.         Close( rexxmessage->rm_Stdin );
  136.  
  137.     if( rexxmessage->rm_Stdout &&
  138.         rexxmessage->rm_Stdout != rexxmessage->rm_Stdin &&
  139.         rexxmessage->rm_Stdout != Output() )
  140.         Close( rexxmessage->rm_Stdout );
  141.  
  142.     DeleteArgstring( (char *) ARG0(rexxmessage) );
  143.     DeleteRexxMsg( rexxmessage );
  144. }
  145.  
  146.  
  147. struct RexxMsg *CreateRexxCommand( struct RexxHost *host, char *buff, BPTR fh )
  148. {
  149.     struct RexxMsg *rexx_command_message;
  150.  
  151.     if( (rexx_command_message = CreateRexxMsg( host->port,
  152.         rexx_extension, host->port->mp_Node.ln_Name)) == NULL )
  153.     {
  154.         return( NULL );
  155.     }
  156.  
  157.     if( (rexx_command_message->rm_Args[0] =
  158.         CreateArgstring(buff,strlen(buff))) == NULL )
  159.     {
  160.         DeleteRexxMsg(rexx_command_message);
  161.         return( NULL );
  162.     }
  163.  
  164.     rexx_command_message->rm_Action = RXCOMM | RXFF_RESULT;
  165.     rexx_command_message->rm_Stdin  = fh;
  166.     rexx_command_message->rm_Stdout = fh;
  167.     
  168.     return( rexx_command_message );
  169. }
  170.  
  171.  
  172. struct RexxMsg *CommandToRexx( struct RexxHost *host, struct RexxMsg *rexx_command_message )
  173. {
  174.     struct MsgPort *rexxport;
  175.     
  176.     Forbid();
  177.  
  178.     if( (rexxport = FindPort(RXSDIR)) == NULL )
  179.     {
  180.         Permit();
  181.         return( NULL );
  182.     }
  183.  
  184.     PutMsg( rexxport, &rexx_command_message->rm_Node );
  185.     
  186.     Permit();
  187.     
  188.     ++host->replies;
  189.     return( rexx_command_message );
  190. }
  191.  
  192.  
  193. struct RexxMsg *SendRexxCommand( struct RexxHost *host, char *buff, BPTR fh )
  194. {
  195.     struct RexxMsg *rcm;
  196.     
  197.     if( rcm = CreateRexxCommand(host, buff, fh) )
  198.         return CommandToRexx( host, rcm );
  199.     else
  200.         return NULL;
  201. }
  202.  
  203.  
  204. void CloseDownARexxHost( struct RexxHost *host )
  205. {
  206.     struct RexxMsg *rexxmsg;
  207.     
  208.     if( host->port )
  209.     {
  210.         /* Port abmelden */
  211.         RemPort( host->port );
  212.         
  213.         /* Auf noch ausstehende Replies warten */
  214.         while( host->replies > 0 )
  215.         {
  216.             WaitPort( host->port );
  217.             
  218.             while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  219.             {
  220.                 if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  221.                 {
  222.                     if( !rexxmsg->rm_Args[15] )
  223.                     {
  224.                         /* Reply zu einem SendRexxCommand()-Call */
  225.                         if( ARexxResultHook )
  226.                             ARexxResultHook( host, rexxmsg );
  227.                     }
  228.                     
  229.                     FreeRexxCommand( rexxmsg );
  230.                     --host->replies;
  231.                 }
  232.                 else
  233.                     ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  234.             }
  235.         }
  236.         
  237.         /* MsgPort leeren */
  238.         while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  239.             ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  240.         
  241.         if( !(host->flags & ARB_HF_USRMSGPORT) )
  242.             DeleteMsgPort( host->port );
  243.     }
  244.     
  245.     if( host->rdargs ) FreeDosObject( DOS_RDARGS, host->rdargs );
  246.     FreeVec( host );
  247. }
  248.  
  249.  
  250. struct RexxHost *SetupARexxHost( char *basename, struct MsgPort *usrport )
  251. {
  252.     struct RexxHost *host;
  253.     int ext = 0;
  254.     
  255.     if( !basename )
  256.         basename = RexxPortBaseName;
  257.     else if( !*basename )
  258.         basename = RexxPortBaseName;
  259.     
  260.     if( !(host = AllocVec(sizeof *host, MEMF_CLEAR)) )
  261.         return NULL;
  262.     
  263.     strcpy( host->portname, basename );
  264.     
  265.     if( usrport )
  266.     {
  267.         host->port   = usrport;
  268.         host->flags |= ARB_HF_USRMSGPORT;
  269.     }
  270.     else if( !(host->port = CreateMsgPort()) )
  271.     {
  272.         FreeVec( host );
  273.         return NULL;
  274.     }
  275.     else
  276.     {
  277.         host->port->mp_Node.ln_Pri = 0;
  278.     }
  279.     
  280.     Forbid();
  281.     
  282.     while( FindPort(host->portname) )
  283.         sprintf( host->portname, "%s.%d", basename, ++ext );
  284.     
  285.     host->port->mp_Node.ln_Name = host->portname;
  286.     AddPort( host->port );
  287.     
  288.     Permit();
  289.     
  290.     if( !(host->rdargs = AllocDosObject(DOS_RDARGS, NULL)) )
  291.     {
  292.         RemPort( host->port );
  293.         if( !usrport ) DeleteMsgPort( host->port );
  294.         FreeVec( host );
  295.         return NULL;
  296.     }
  297.     
  298.     host->rdargs->RDA_Flags = RDAF_NOPROMPT;
  299.     
  300.     return( host );
  301. }
  302.  
  303.  
  304. /* StateMachine für FindRXCommand() */
  305.  
  306. static inline char *scmp( char *inp, char *str )
  307. {
  308.     while( *str && *inp )
  309.         if( *inp++ != *str++ )
  310.             return NULL;
  311.     
  312.     /* Reststring zurückgeben */
  313.     return inp;
  314. }
  315.  
  316. static int find( char *input )
  317. {
  318.     struct arb_p_state *st = arb_p_state;
  319.     struct arb_p_link *ad;
  320.     char *ni, tmp[36], *s;
  321.     
  322.     ni = tmp;
  323.     while( *input && ni-tmp < 32 )
  324.         *ni++ = toupper( *input++ );
  325.     *ni = 0;
  326.     input = tmp;
  327.     
  328.     while( *input )
  329.     {
  330.         /* Terminalzustand erreicht? */
  331.         if( !st->pa )
  332.         {
  333.             if( *input )
  334.                 return -1;
  335.             else
  336.                 return st->cmd;
  337.         }
  338.         
  339.         /* Wo geht's weiter? */
  340.         ni = 0;
  341.         for( ad = st->pa; s = ad->str; ad++ )
  342.         {
  343.             /* die Links sind absteigend sortiert */
  344.             if( *input > *s )
  345.                 break;
  346.             
  347.             if( *input == *s )
  348.                 if( ni = scmp(input+1, s+1) )
  349.                     break;
  350.         }
  351.         
  352.         /* Nirgends... */
  353.         if( !ni )
  354.             return -1;
  355.         
  356.         /* Zustandsüberführung */
  357.         st = arb_p_state + ad->dst;
  358.         input = ni;
  359.     }
  360.     
  361.     return st->cmd;
  362. }
  363.  
  364. struct rxs_command *FindRXCommand( char *com )
  365. {
  366.     int cmd;
  367.     
  368.     cmd = find( com );
  369.     
  370.     if( cmd == -1 )
  371.         return NULL;
  372.     else
  373.         return( rxs_commandlist + cmd );
  374. }
  375.  
  376.  
  377. static struct rxs_command *ParseRXCommand( char **arg )
  378. {
  379.     char com[256], *s, *t;
  380.     
  381.     s = *arg;
  382.     t = com;
  383.     
  384.     while( *s && *s != ' ' && *s != '\n' )
  385.         *t++ = *s++;
  386.     
  387.     *t = '\0';
  388.     while( *s == ' ' ) ++s;
  389.     *arg = s;
  390.     
  391.     return( FindRXCommand( com ) );
  392. }
  393.  
  394.  
  395. static char *CreateVAR( struct rxs_stemnode *stem )
  396. {
  397.     char *var;
  398.     struct rxs_stemnode *s;
  399.     long size = 0;
  400.     
  401.     if( !stem || stem == (struct rxs_stemnode *) -1L )
  402.         return( (char *) stem );
  403.     
  404.     for( s = stem; s; s = s->succ )
  405.         size += strlen( s->value ) + 1;
  406.     
  407.     if( !(var = AllocVec( size + 1, MEMF_ANY )) )
  408.         return( (char *) -1 );
  409.     
  410.     *var = '\0';
  411.     
  412.     for( s = stem; s; s = s->succ )
  413.     {
  414.         strcat( var, s->value );
  415.         if( s->succ )
  416.             strcat( var, " " );
  417.     }
  418.     
  419.     return( var );
  420. }
  421.  
  422.  
  423. static struct rxs_stemnode *new_stemnode( struct rxs_stemnode **first, struct rxs_stemnode **old )
  424. {
  425.     struct rxs_stemnode *new;
  426.     
  427.     if( !(new = AllocVec(sizeof(struct rxs_stemnode), MEMF_CLEAR)) )
  428.     {
  429.         return( NULL );
  430.     }
  431.     else
  432.     {
  433.         if( *old )
  434.         {
  435.             (*old)->succ = new;
  436.             (*old) = new;
  437.         }
  438.         else
  439.         {
  440.             *first = *old = new;
  441.         }
  442.     }
  443.     
  444.     return( new );
  445. }
  446.  
  447.  
  448. static void free_stemlist( struct rxs_stemnode *first )
  449. {
  450.     struct rxs_stemnode *next;
  451.     
  452.     if( (long) first == -1 )
  453.         return;
  454.     
  455.     for( ; first; first = next )
  456.     {
  457.         next = first->succ;
  458.         if( first->name  ) FreeVec( first->name );
  459.         if( first->value ) FreeVec( first->value );
  460.         FreeVec( first );
  461.     }
  462. }
  463.  
  464.  
  465. char *StrDup( char *s )
  466. {
  467.     char *t = AllocVec( strlen(s)+1, MEMF_ANY );
  468.     if( t ) strcpy( t, s );
  469.     return t;
  470. }
  471.  
  472.  
  473. static struct rxs_stemnode *CreateSTEM( struct rxs_command *rxc, LONG *resarray, char *stembase )
  474. {
  475.     struct rxs_stemnode *first = NULL, *old = NULL, *new;
  476.     char resb[512], *rs, *rb;
  477.     char longbuff[16];
  478.     
  479.     rb = resb;
  480.     if( stembase )
  481.     {
  482.         while( *stembase )
  483.             *rb++ = toupper( *stembase++ );
  484.     }
  485.     *rb = '\0';
  486.     
  487.     rb = resb + strlen(resb);
  488.     rs = rxc->results;
  489.     
  490.     while( *rs )
  491.     {
  492.         char *t = rb;
  493.         BOOL optn = FALSE, optm = FALSE;
  494.         
  495.         while( *rs && *rs != ',' )
  496.         {
  497.             if( *rs == '/' )
  498.             {
  499.                 ++rs;
  500.                 if( *rs == 'N' ) optn = TRUE;
  501.                 else if( *rs == 'M' ) optm = TRUE;
  502.             }
  503.             else
  504.                 *t++ = *rs;
  505.             
  506.             ++rs;
  507.         }
  508.         
  509.         if( *rs == ',' ) ++rs;
  510.         *t = '\0';
  511.         
  512.         /*
  513.          * Resultat(e) erzeugen
  514.          */
  515.         
  516.         if( !*resarray )
  517.         {
  518.             ++resarray;
  519.             continue;
  520.         }
  521.         
  522.         if( optm )
  523.         {
  524.             long *r, index = 0;
  525.             LONG **subarray = (LONG **) *resarray++;
  526.             struct rxs_stemnode *countnd;
  527.             
  528.             /* Anzahl der Elemente */
  529.             
  530.             if( !(new = new_stemnode(&first, &old)) )
  531.             {
  532.                 free_stemlist( first );
  533.                 return( (struct rxs_stemnode *) -1L );
  534.             }
  535.             countnd = new;
  536.             
  537.             /* Die Elemente selbst */
  538.             
  539.             while( r = *subarray++ )
  540.             {
  541.                 if( !(new = new_stemnode(&first, &old)) )
  542.                 {
  543.                     free_stemlist( first );
  544.                     return( (struct rxs_stemnode *) -1L );
  545.                 }
  546.                 
  547.                 sprintf( t, ".%ld", index++ );
  548.                 new->name = StrDup( resb );
  549.                 
  550.                 if( optn )
  551.                 {
  552.                     sprintf( longbuff, "%ld", *r );
  553.                     new->value = StrDup( longbuff );
  554.                 }
  555.                 else
  556.                 {
  557.                     new->value = StrDup( (char *) r );
  558.                 }
  559.             }
  560.             
  561.             /* Die Count-Node */
  562.             
  563.             strcpy( t, ".COUNT" );
  564.             countnd->name = StrDup( resb );
  565.             
  566.             sprintf( longbuff, "%ld", index );
  567.             countnd->value = StrDup( longbuff );
  568.         }
  569.         else
  570.         {
  571.             /* Neue Node anlegen */
  572.             if( !(new = new_stemnode(&first, &old)) )
  573.             {
  574.                 free_stemlist( first );
  575.                 return( (struct rxs_stemnode *) -1L );
  576.             }
  577.             
  578.             new->name = StrDup( resb );
  579.             
  580.             if( optn )
  581.             {
  582.                 sprintf( longbuff, "%ld", *((long *) *resarray) );
  583.                 new->value = StrDup( longbuff );
  584.                 ++resarray;
  585.             }
  586.             else
  587.             {
  588.                 new->value = StrDup( (char *) (*resarray++) );
  589.             }
  590.         }
  591.     }
  592.     
  593.     return( first );
  594. }
  595.  
  596.  
  597. static void DoRXCommand( struct RexxHost *host, struct RexxMsg *rexxmsg )
  598. {
  599.     struct rxs_command *rxc;
  600.     char *argb = NULL, *arg;
  601.     
  602.     LONG *array = NULL;
  603.     LONG *argarray;
  604.     LONG *resarray;
  605.     
  606.     char *cargstr = NULL;
  607.     long rc=20, rc2=0;
  608.     char *result = NULL;
  609.     
  610.     if( !(argb = AllocVec(strlen((char *) ARG0(rexxmsg)) + 2, MEMF_ANY)) )
  611.     {
  612.         rc2 = ERROR_NO_FREE_STORE;
  613.         goto drc_cleanup;
  614.     }
  615.     
  616.     /* welches Kommando? */
  617.     
  618.     strcpy( argb, (char *) ARG0(rexxmsg) );
  619.     strcat( argb, "\n" );
  620.     arg = argb;
  621.     
  622.     if( !( rxc = ParseRXCommand( &arg ) ) )
  623.     {
  624.         if( arg = ExpandRXCommand( host, (char *) ARG0(rexxmsg) ) )
  625.         {
  626.             FreeVec( argb );
  627.             if( !(argb = AllocVec( strlen(arg) + 2, MEMF_ANY )) )
  628.             {
  629.                 rc2 = ERROR_NO_FREE_STORE;
  630.                 goto drc_cleanup;
  631.             }
  632.             
  633.             strcpy( argb, arg );
  634.             strcat( argb, "\n" );
  635.             FreeVec( arg );
  636.             arg = argb;
  637.             
  638.             rxc = ParseRXCommand( &arg );
  639.         }
  640.     }
  641.     
  642.     if( !rxc )
  643.     {
  644.         /* Msg an ARexx schicken, vielleicht existiert ein Skript */
  645.         struct RexxMsg *rm;
  646.         
  647.         if( rm = CreateRexxCommand(host, (char *) ARG0(rexxmsg), NULL) )
  648.         {
  649.             /* Original-Msg merken */
  650.             rm->rm_Args[15] = (STRPTR) rexxmsg;
  651.             
  652.             if( CommandToRexx(host, rm) )
  653.             {
  654.                 /* Reply wird später vom Dispatcher gemacht */
  655.                 if( argb ) FreeVec( argb );
  656.                 return;
  657.             }
  658.             else
  659.                 rc2 = ERROR_NOT_IMPLEMENTED;
  660.         }
  661.         else
  662.             rc2 = ERROR_NO_FREE_STORE;
  663.         
  664.         goto drc_cleanup;
  665.     }
  666.     
  667.     if( !(rxc->flags & ARB_CF_ENABLED) )
  668.     {
  669.         rc = -10;
  670.         rc2 = (long) "Command disabled";
  671.         goto drc_cleanup;
  672.     }
  673.     
  674.     /* Speicher für Argumente etc. holen */
  675.     
  676.     (rxc->function)( host, (void **) &array, RXIF_INIT, rexxmsg );
  677.     cargstr = AllocVec( rxc->args ? 15+strlen(rxc->args) : 15, MEMF_ANY );
  678.     
  679.     if( !array || !cargstr )
  680.     {
  681.         rc2 = ERROR_NO_FREE_STORE;
  682.         goto drc_cleanup;
  683.     }
  684.     
  685.     argarray = array + 2;
  686.     resarray = array + rxc->resindex;
  687.     
  688.     /* Argumente parsen */
  689.     
  690.     if( rxc->results )
  691.         strcpy( cargstr, "VAR/K,STEM/K" );
  692.     else
  693.         *cargstr = '\0';
  694.     
  695.     if( rxc->args )
  696.     {
  697.         if( *cargstr )
  698.             strcat( cargstr, "," );
  699.         strcat( cargstr, rxc->args );
  700.     }
  701.     
  702.     if( *cargstr )
  703.     {
  704.         host->rdargs->RDA_Source.CS_Buffer = arg;
  705.         host->rdargs->RDA_Source.CS_Length = strlen(arg);
  706.         host->rdargs->RDA_Source.CS_CurChr = 0;
  707.         host->rdargs->RDA_DAList = NULL;
  708.         host->rdargs->RDA_Buffer = NULL;
  709.         
  710.         if( !ReadArgs(cargstr, argarray, host->rdargs) )
  711.         {
  712.             rc = 10;
  713.             rc2 = IoErr();
  714.             goto drc_cleanup;
  715.         }
  716.     }
  717.     
  718.     /* Funktion aufrufen */
  719.     
  720.     (rxc->function)( host, (void **) &array, RXIF_ACTION, rexxmsg );
  721.     
  722.     rc = array[0];
  723.     rc2 = array[1];
  724.     
  725.     /* Resultat(e) auswerten */
  726.     
  727.     if( rxc->results && rc==0 &&
  728.         (rexxmsg->rm_Action & RXFF_RESULT) )
  729.     {
  730.         struct rxs_stemnode *stem, *s;
  731.         
  732.         stem = CreateSTEM( rxc, resarray, (char *)argarray[1] );
  733.         result = CreateVAR( stem );
  734.         
  735.         if( result )
  736.         {
  737.             if( argarray[0] )
  738.             {
  739.                 /* VAR */
  740.                 if( (long) result == -1 )
  741.                 {
  742.                     rc = 20;
  743.                     rc2 = ERROR_NO_FREE_STORE;
  744.                 }
  745.                 else
  746.                 {
  747.                     char *rb;
  748.                     
  749.                     for( rb = (char *) argarray[0]; *rb; ++rb )
  750.                         *rb = toupper( *rb );
  751.                     
  752.                     if( SetRexxVar( (struct Message *) rexxmsg,
  753.                         *((char *)argarray[0]) ? (char *)argarray[0] : "RESULT",
  754.                         result, strlen(result) ) )
  755.                     {
  756.                         rc = -10;
  757.                         rc2 = (long) "Unable to set Rexx variable";
  758.                     }
  759.                     
  760.                     FreeVec( result );
  761.                 }
  762.                 
  763.                 result = NULL;
  764.             }
  765.             
  766.             if( !rc && argarray[1] )
  767.             {
  768.                 /* STEM */
  769.                 if( (long) stem == -1 )
  770.                 {
  771.                     rc = 20;
  772.                     rc2 = ERROR_NO_FREE_STORE;
  773.                 }
  774.                 else
  775.                 {
  776.                     for( s = stem; s; s = s->succ )
  777.                         rc |= SetRexxVar( (struct Message *) rexxmsg, s->name, s->value, strlen(s->value) );
  778.                     
  779.                     if( rc )
  780.                     {
  781.                         rc = -10;
  782.                         rc2 = (long) "Unable to set Rexx variable";
  783.                     }
  784.                     
  785.                     if( result && (long) result != -1 )
  786.                         FreeVec( result );
  787.                 }
  788.                 
  789.                 result = NULL;
  790.             }
  791.             
  792.             /* Normales Resultat: Möglich? */
  793.             
  794.             if( (long) result == -1 )
  795.             {
  796.                 /* Nein */
  797.                 rc = 20;
  798.                 rc2 = ERROR_NO_FREE_STORE;
  799.                 result = NULL;
  800.             }
  801.         }
  802.         
  803.         free_stemlist( stem );
  804.     }
  805.     
  806. drc_cleanup:
  807.  
  808.     /* Nur RESULT, wenn weder VAR noch STEM */
  809.     
  810.     ReplyRexxCommand( rexxmsg, rc, rc2, result );
  811.     
  812.     /* benutzten Speicher freigeben */
  813.     
  814.     if( result ) FreeVec( result );
  815.     FreeArgs( host->rdargs );
  816.     if( cargstr ) FreeVec( cargstr );
  817.     if( array ) (rxc->function)( host, (void **) &array, RXIF_FREE, rexxmsg );
  818.     if( argb ) FreeVec( argb );
  819. }
  820.  
  821.  
  822. void ARexxDispatch( struct RexxHost *host )
  823. {
  824.     struct RexxMsg *rexxmsg;
  825.  
  826.     while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  827.     {
  828.         if( (rexxmsg->rm_Action & RXCODEMASK) != RXCOMM )
  829.         {
  830.             /* Keine Rexx-Message */
  831.             ReplyMsg( (struct Message *) rexxmsg );
  832.         }
  833.         else if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  834.         {
  835.             struct RexxMsg *org = (struct RexxMsg *) rexxmsg->rm_Args[15];
  836.             
  837.             if( org )
  838.             {
  839.                 /* Reply zu durchgereichter Msg */
  840.                 if( rexxmsg->rm_Result1 != 0 )
  841.                 {
  842.                     /* Befehl unbekannt */
  843.                     ReplyRexxCommand( org, 20, ERROR_NOT_IMPLEMENTED, NULL );
  844.                 }
  845.                 else
  846.                 {
  847.                     ReplyRexxCommand( org, 0, 0, (char *) rexxmsg->rm_Result2 );
  848.                 }
  849.             }
  850.             else
  851.             {
  852.                 /* Reply zu einem SendRexxCommand()-Call */
  853.                 if( ARexxResultHook )
  854.                     ARexxResultHook( host, rexxmsg );
  855.             }
  856.             
  857.             FreeRexxCommand( rexxmsg );
  858.             --host->replies;
  859.         }
  860.         else if( ARG0(rexxmsg) )
  861.         {
  862.             DoRXCommand( host, rexxmsg );
  863.         }
  864.         else
  865.         {
  866.             ReplyMsg( (struct Message *) rexxmsg );
  867.         }
  868.     }
  869. }
  870.  
  871.